<?php

/**
 * This file is part of Webman AI.
 *
 * @author    walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link      http://www.workerman.net/
 */

namespace plugin\ai\app\controller;

use plugin\ai\api\Audio;
use plugin\ai\app\event\data\ModelRequestData;
use plugin\ai\app\event\data\ModelResponseData;
use plugin\ai\app\handler\driver\Spark;
use plugin\ai\app\service\Common;
use plugin\ai\app\service\User;
use plugin\user\api\Limit;
use support\exception\BusinessException;
use support\Log;
use support\Request;
use support\Response;
use Throwable;
use Webman\Event\Event;
use Workerman\Protocols\Http\Chunk;

class AudioController extends Base
{

    /**
     * 不需要登录的方法
     *
     * @var string[]
     */
    protected $noNeedLogin = ['speech'];

    /**
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function speech(Request $request): Response
    {
        $model = $request->input('model', 'tts-1');
        $voice = $request->input('voice', 'echo');
        if ($voice === 'yingying') {
            $model = 'ying';
        }
        if ($error = static::tryReduceBalance($model)) {
            return json(['error' => ['message' => $error]]);
        }
        $connection = $request->connection;
        $modelRequestData = new ModelRequestData();
        $modelRequestData->data = [
            'model' => $model,
            'input' => $request->input('input', '语音内容为空'),
            'voice' => $voice,
        ];
        $modelRequestData->options = [
            'stream' => function($buffer) use ($connection) {
                $connection->send(new Chunk($buffer));
            },
            'complete' => function($result, $response) use ($connection, $modelRequestData) {
                if (is_array($result)) {
                    Log::error(json_encode($result, JSON_UNESCAPED_UNICODE));
                }
                $connection->send(new Chunk(''));
                $responseData = new ModelResponseData();
                $responseData->data = $result;
                $responseData->modelRequestData = $modelRequestData;
                Event::dispatch('ai.audio.speech.response', $responseData);
            },
            'error' => function($exception) use ($connection) {
                echo $exception;
            },
        ];
        Event::dispatch('ai.audio.speech.request', $modelRequestData);
        Audio::speech($modelRequestData->data, $modelRequestData->options);
        return response(' ')->withHeaders([
            "Content-Type" => "audio/mpeg",
            "Transfer-Encoding" => "chunked",
        ]);
    }

    /**
     * 讯飞听写鉴权
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function xunfeiIatAuth(Request $request)
    {
        // 频率限制
        $loginUserId = session('user.id') ?: session('user.uid');
        $freeCountPerDay = $loginUserId ? 500 : 200;
        $isVip = $loginUserId && User::isVip($loginUserId);
        $freeCountPerDay = $isVip ? 1000 : $freeCountPerDay;
        try {
            if ($loginUserId) {
                Limit::perDay($loginUserId . "-ai-voice-", $freeCountPerDay);
            }
            $ip = request()->getRealIp();
            // 非内网ip时
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                Limit::perDay("$ip-ai-voice-", $freeCountPerDay);
            } else {
                $session = $request->session();
                Limit::perDay($session->getId() ."-ai-voice-", $freeCountPerDay);
            }
        } catch (Throwable $e) {
            return $this->json(1, '你语音额度今日已经用完，如需继续使用，请续费');
        }

        $addr = "wss://iat-api.xfyun.cn/v2/iat";
        $setting = \plugin\ai\app\service\Audio::getSetting();

        return $this->json(0, 'ok', [
            'id' => $setting['xunfei_iat_appid'],
            'auth' => Spark::auth($setting['xunfei_iat_appid'], $setting['xunfei_iat_apikey'], $setting['xunfei_iat_secret_key'], $addr)
        ]);
    }

}